import * as DT from 'dt-sdk/library/DT'
import moment from 'moment'
import { mapGetters, mapMutations, Store } from 'vuex'
import { viewer } from '@/components/dt-scene/index.vue'
import clock from '@/mixin/clock'
import { pauseSend, resumeSend } from '@/api/scene'
let clockEvent = null
export default {
  name: 'Controls',
  mixins: [clock],
  inject: ['changeTime'],
  inject: ['changeTime', 'requestMode'],
  props: {
    sceneTime: {
      type: Object,
      required: true,
      default:() => {
        return {}
      }
    }
  },
  data() {
    return {
      controls: {
        isPlayed: true,
        speed: null,
        timeDirection: true
      },
      speedData: {
        marks: {
          1: '1X',
          150: '150X',
          300: '300X'
        }
      },
      timeData: {
        value: 1,
        min: 0,
        max: 0,
        marks: {}
      },
      selectedTime: null,
      isDrag: false,
      timeout: null, // 防抖使用
    }
  },
  computed: {
    ...mapGetters(['currentTime', 'sceneMode']),
  },
  watch: {
    /**
     * 修改时间轴数据
     * @author Farley
     * @date 2021-10-27
     * @param {any} val
     * @returns {any}
     */
    sceneTime: {
      handler: function (nv, ov) {
        this.initCesiumTime()
      },
      deep: true
    },

    sceneMode: {
      handler: function (nv, ov) {
        if (!nv) {
          viewer.cesiumViewer.clock.multiplier = 1
        } else {
          viewer.cesiumViewer.clock.multiplier = this.controls.speed
        }
        this.initCesiumTime()
      },
      // immediate: true
    },
    sceneStatus: {
      handler(val) {
        val.isInited && this.initCesiumTime()
      },
      immediate: true,
      deep: true
    },

  },
  mounted() {
    // 解决不手动修改场景时间也会触发向外暴露的 changeTime 事件
    // 滑块按钮
    let timeSliderBtn = document.getElementsByClassName('el-slider__button-wrapper')[0]
    timeSliderBtn.onmousedown = () => {
      this.isDrag = true
      // timeSliderBtn.onmouseleave = () => {
      //   this.isDrag = false
      // }
    }
    timeSliderBtn.onmouseup = () => {
      this.isDrag = false
    }
    // 滑块按钮下的轴
    let sliderRunway = document.getElementsByClassName('el-slider__runway')[0]
    sliderRunway.onmousedown = () => {
      this.isDrag = true
      // timeSliderBtn.onmouseleave = () => {
      //   this.isDrag = false
      // }
    }
    sliderRunway.onmouseup = () => {
      this.isDrag = false
    }
    let interval = setInterval(() => {
      if (viewer) {
        this.initCesiumTime()
        clearInterval(interval)
      }
    }, 100)



  },
  beforeDestroy() {
    // 移除之前的事件
    if (clockEvent) {
      clockEvent()
    }
    // viewer.cesiumViewer.clock.onTick.removeEventListener(this.handleOnTick)
  },
  methods: {
    ...mapMutations('app', ['SET_CURRENT_TIME', 'SET_SPEED']),

    initCesiumTime() {
      let time = this.sceneTime
      // 移除之前的事件
      if (clockEvent) {
        clockEvent()
      }
      if (this.sceneMode) {
        //回访模式
        if (time.startTime && time.endTime) {
          let startTime = DT.Cesium.JulianDate.fromIso8601(time.startTime)
          let stopTime = DT.Cesium.JulianDate.fromIso8601(time.endTime)
          viewer.cesiumViewer.clock.startTime = startTime
          viewer.cesiumViewer.clock.currentTime = startTime
          viewer.cesiumViewer.clock.stopTime = stopTime
          viewer.cesiumViewer.clock.shouldAnimate = true
          this.timelineInit(time.startTime, time.endTime)
          // 场景时间变化事件
          clockEvent = viewer.cesiumViewer.clock.onTick.addEventListener(this.handleOnTick)
        }
      } else {
        // let now = moment().utcOffset(8).format('YYYY-MM-DDTHH:mm:ss') + 'Z'
        // let time = DT.Cesium.JulianDate.fromIso8601(now)
        let time = DT.Cesium.JulianDate.fromDate(new Date())
        // viewer.cesiumViewer.clock.startTime = startTime
        viewer.cesiumViewer.clock.currentTime = time
        viewer.cesiumViewer.clock.shouldAnimate = true
        clockEvent = viewer.cesiumViewer.clock.onTick.addEventListener(this.handleOnTickReal)
      }
    },
    /**
     * 场景时钟变化回调
     * @author Farley、ZZQ
     * @date 2021-10-28
     * @param {any} time
     * @returns {any}
     */
    handleOnTick({ currentTime }) {
      let time = moment(DT.Cesium.JulianDate.toIso8601(currentTime)).utc().format('YYYY-MM-DDTHH:mm:ss') + 'Z'
      // 设置 vuex 中的 currentTime - 当前场景时间，时间格式 UTC
      if (this.currentTime !== time) {
        this.SET_CURRENT_TIME(time)
      }
      /*1.基础使用参数，当前时间时间戳，开始时间时间戳，结束时间时间戳*/
      let timeStamp = new Date(DT.Cesium.JulianDate.toIso8601(currentTime)).getTime()
      let startTime = new Date(this.sceneTime.startTime).getTime()
      let endTime = new Date(this.sceneTime.endTime).getTime()
      /*2.首先解决场景时间如果超过开始时间到结束时间的范围区间，结束场景运行,否则继续执行*/
      if (timeStamp > 0 && (startTime > timeStamp || timeStamp > endTime)) {
        //场景运行倍数赋值为0，停止场景
        viewer.cesiumViewer.clock.multiplier = 0
        //将时间轴暂停播放按钮改为暂停状态
        this.controls.isPlayed = false
        //  由于实时运行状态下在场景倍数停止一瞬间时间会存在超出的问题，所以重新赋值时间；无法确定当前是结束时间还是起始时间所以使用三元判断
        startTime > timeStamp
          ? viewer.cesiumViewer.clock.currentTime = DT.Cesium.JulianDate.fromDate(new Date(this.sceneTime.startTime))
          : viewer.cesiumViewer.clock.currentTime = DT.Cesium.JulianDate.fromDate(new Date(this.sceneTime.endTime))
        return
      }
      /*3.判断当前时间是否到达时间轴的起始或终止时间，如果到达则更新时间轴。*/
      if (this.timeData.min > timeStamp || timeStamp > this.timeData.max) {
        //timeLine：当前时间用于后续重新赋值，dayTime：一天时间毫秒值
        let timeLine = timeStamp, dayTime = 24 * 60 * 60 * 1000
        //判断当前运行状态；前进：true，后退：false
        if (this.controls.timeDirection) {
          //采用三元进行判断，如果场景结束时间减当前时间大于一天，结束时间为当前时间加1天，否则采用场景结束时间
          endTime - timeStamp > dayTime
            ? timeLine = timeStamp + dayTime
            : timeLine = endTime
          this.timelineInit(timeStamp, timeLine)
          //  更新当前时间轴滑块到开始
          this.timeData.value = timeStamp
        } else {
          //如果为后退
          //采用三元进行判断，如果场景当前时间减场景开始时间大于一天，开始时间为当前时间减1天，否则采用场景开始时间
          timeStamp - startTime > dayTime ? timeLine = timeStamp - dayTime : timeLine = startTime
          this.timelineInit(timeLine, timeStamp)
          //  更新当前时间轴滑块到时间轴末尾
          this.timeData.value = timeStamp
        }
        /*4.否则继续运行。*/
      } else {
        this.timeData.value = timeStamp
      }
    },
    handleOnTickReal({ currentTime }) {
      let time = moment(DT.Cesium.JulianDate.toIso8601(currentTime)).utc().format('YYYY-MM-DDTHH:mm:ss') + 'Z'
      // 设置 vuex 中的 currentTime - 当前场景时间，时间格式 UTC
      if (this.currentTime !== time) {
        this.SET_CURRENT_TIME(time)
      }
    },
    /**
     * 时间轴改变修改场景当前时间
     * @author Farley
     * @date 2021-10-26
     * @param {any} val
     * @returns {any}
     */
    changeCurrentTimeOfSlider(val) {
      // 如果是在拖拽，与后台同步，并触发时间改变事件
      if (this.isDrag) {
        viewer.cesiumViewer.clock.currentTime = DT.Cesium.JulianDate.fromDate(new Date(val))
        // 防抖
        if (this.timeout) {
          clearTimeout(this.timeout)
        }
        // console.log('触发拖拽时间', val);
        this.timeout = setTimeout(() => {
          // let tmpTime = this.timeData.value
          // this.syncClock({ startTime: tmpTime }, () => {
          this.changeTime(this.timeData.value, this.controls.speed)
          // })
        }, 100);
      } else {
        viewer.cesiumViewer.clock.currentTime = DT.Cesium.JulianDate.fromDate(new Date(val))
      }
    },
    /**
     * @author ZZQ
     * date 2021-10-26
     * 初始化时间轴
     * */
    timelineInit(startTime, endTime) {
      /*1.初始方法内全局变量*/
      //场景开始时间毫秒值，
      let sceneStartTime = new Date(startTime).getTime()
      //场景结束时间毫秒值
      let sceneEndTime = new Date(endTime).getTime()
      //场景时间差
      let timeDiff = sceneEndTime - sceneStartTime
      //时间轴上需要显示的时间个数
      let timeNum = 10
      //时间轴均分的时间值，用于后续时间轴按比例分配后的时间计算系数
      let timeLineNum = 0
      //一天毫秒值
      let secondTime = 24 * 60 * 60 * 1000
      /*2.时间轴始终显示1天的时间量，如果时间差值大于一天则结束时间为开始时间加1天，小于1天使用场景全部时间；
      大于：时间轴计算系数 = 一天毫秒值 / 时间个数；
      小于：时间轴计算系数 = 场景所有时间差 / 时间个数
      */
      if (timeDiff > secondTime) {
        timeLineNum = secondTime / timeNum
      } else {
        timeLineNum = timeDiff / timeNum
      }
      //设置时间轴滑块最大最小区间（利用时间戳赋值）
      this.timeData.min = sceneStartTime
      //加1:因为刚好是结束时间时,时间轴上最后一个值不显示
      this.timeData.max = sceneStartTime + timeLineNum * timeNum + 1
      //赋值当前时间
      this.timeData.value = sceneStartTime
      //时间轴上显示时间的容器
      this.timeData.marks = {}
      //开始时间的天数，用于后面显示年月日做比较
      let day = this.getBJTime(sceneStartTime).day
      //循环遍历时间轴上显示的时间
      for (let i = 0; i <= timeNum; i++) {
        //当前刻度显示时间
        let time = this.getBJTime(sceneStartTime + timeLineNum * i)
        //如果为初始值显示年月日，或者跨天显示年月日
        if (i === 0 || (time.day > day || time.day < day)) {
          //记录时间轴刻度上个显示天数
          day = time.day
          //时间轴初始时间年月日,样式修改，由于最后一个时间显示样式比较难看，单独修改该条样式
          let width = '75px', marginLeft = '-6px'
          let yearStyle = { color: '#23e0f1', display: 'inline-block', top: '-13px', marginLeft: '15px' },
            dayStyle = { top: '5px', marginLeft: '15px' }
          if (i == timeNum) {
            yearStyle['width'] = width
            yearStyle['marginLeft'] = marginLeft
            dayStyle['marginLeft'] = marginLeft
          }
          this.$set(this.timeData.marks, sceneStartTime + timeLineNum * i, {
            style: yearStyle,
            label: time.date
          })
          //时间轴初始时间
          this.$set(this.timeData.marks, sceneStartTime + timeLineNum * i + 1, {
            style: dayStyle,
            label: time.hour
          })
        } else {
          this.$set(this.timeData.marks, sceneStartTime + timeLineNum * i, {
            style: { top: '5px' },
            label: time.hour
          })
        }
      }
    },
    /**
     * @author ZZQ
     * date 2021-10-26
     * 时间跳转
     * */
    changeCurrentTime() {
      if (this.selectedTime != null) {
        /*1.方法内全局表量声明*/
        //当前时间时间戳
        let currentTime = new Date(this.selectedTime).getTime()
        //场景开始时间时间戳
        let startTime = new Date(this.sceneTime.startTime).getTime()
        //场景结束时间时间戳
        let endTime = new Date(this.sceneTime.endTime).getTime()
        //时间选择范围验证
        if (currentTime < startTime || currentTime > endTime) return this.$message.error('时间不能小于场景开始时间或大于场景结束时间')
        //判断当前时间运行是前进还是后退，前进：正常传值；后退：将从时间轴最后往前运行
        if (this.controls.timeDirection) {
          this.timelineInit(this.selectedTime, this.sceneTime.endTime)
        } else {
          let timeLineStart = currentTime, dayTime = 24 * 60 * 60 * 1000
          if (currentTime - startTime > dayTime) {
            timeLineStart = currentTime - dayTime
          } else {
            timeLineStart = startTime
          }
          this.timelineInit(timeLineStart, this.selectedTime)
          //  更新当前时间轴滑块到时间轴末尾
          this.timeData.value = currentTime
        }
        viewer.cesiumViewer.clock.currentTime = DT.Cesium.JulianDate.fromDate(new Date(this.selectedTime))
        this.changeTime(tmpTime, this.controls.speed)
      }
    },
    /**
     * @author ZZQ
     * date 2021-10-26
     * 气泡弹窗格式化显示内容
     * */
    formatTime(data) {
      let fromatTime = this.getBJTime(data)
      return fromatTime.date + ' ' + fromatTime.time
    }
    ,
    /**
     * @author ZZQ
     * date 2021-10-26
     * 时间转换
     * */
    getBJTime(time) {
      const add0 = num => (num < 10 ? '0' + num : num)
      let date, y, m, d, h, mm, s
      date = new Date(time)
      y = date.getFullYear()
      m = add0(date.getMonth() + 1)
      d = add0(date.getDate())
      h = add0(date.getHours())
      mm = add0(date.getMinutes())
      s = add0(date.getSeconds())
      return {
        date: `${y}-${m}-${d}`,
        time: `${h}:${mm}:${s}`,
        hour: `${h}:${mm}`,
        day: d
      }
    }
    ,
    /**
     * 前进
     * @author Farley
     * @date 2021-10-25
     * @returns {any}
     */
    toggleForward() {
      viewer.cesiumViewer.clock.multiplier = this.controls.speed
      this.controls.isPlayed = true
      //控制场景暂停又开始后的速度正负取值
      this.controls.timeDirection = true
      this.SET_SPEED(this.controls.speed)
    }
    ,
    /**
     * 后退
     * @author Farley
     * @date 2021-10-25
     * @returns {any}
     */
    toggleBack() {
      this.controls.isPlayed = true
      //控制场景暂停又开始后的速度正负取值
      this.controls.timeDirection = false
      viewer.cesiumViewer.clock.multiplier = -this.controls.speed
      this.SET_SPEED(-this.controls.speed)
    }
    ,
    /**
     * 通过滑块调整速度
     * @author Farley
     * @date 2021-10-25
     * @param {any} val
     * @returns {any}
     */
    changeSpeed(val) {
      this.controls.speed = val
      //如果当前状态为暂停速度为0，否则速度的正负区间取决于当前是前进还是后退
      let speed = this.controls.timeDirection ? val : -val
      let curSpeed = this.controls.isPlayed ? speed : 0
      this.SET_SPEED(curSpeed)
      // 同步时钟
      // this.syncClock({ step: curSpeed }, () => {
      viewer.cesiumViewer.clock.multiplier = curSpeed
      this.changeTime(this.timeData.value, this.controls.speed)
      // })
    }
    ,
    /**
     * 场景减速
     * @author Farley
     * @date 2021-10-25
     * @returns {any}
     */
    speedDown() {
      let preSpeed = viewer.cesiumViewer.clock.multiplier
      if (preSpeed >= 300 || preSpeed <= -300) return
      let curSpeed = preSpeed > 1 ? preSpeed - 1 : preSpeed === 1 ? 1 : preSpeed + 1
      this.controls.speed = Math.abs(curSpeed)
      // 同步时钟
      // this.syncClock({ step: curSpeed }, () => {
      viewer.cesiumViewer.clock.multiplier = curSpeed
      this.changeTime(this.timeData.value, this.controls.speed)
      // })
    }
    ,
    /**
     * 场景加速
     * @author Farley
     * @date 2021-10-25
     * @returns {any}
     */
    speedUp() {
      let preSpeed = viewer.cesiumViewer.clock.multiplier
      if (preSpeed >= 300 || preSpeed <= -300) return
      let curSpeed = preSpeed > 0 ? preSpeed + 1 : preSpeed - 1
      this.controls.speed = Math.abs(curSpeed)
      // 同步时钟
      // this.syncClock({ step: curSpeed }, () => {
      viewer.cesiumViewer.clock.multiplier = curSpeed
      this.changeTime(this.timeData.value, this.controls.speed)
      // })
    }
    ,
    /**
     * 切换场景播放 / 暂停
     * @author Farley
     * @date 2021-10-25
     * @returns {any}
     */
    togglePlay() {
      this.controls.isPlayed = !this.controls.isPlayed
      let speed = this.controls.timeDirection ? this.controls.speed : -this.controls.speed
      viewer.cesiumViewer.clock.multiplier = this.controls.isPlayed ? speed : 0
      if (this.controls.isPlayed) {
        // 暂停
        resumeSend({
          sceneId: this.sceneId,
          userId: this.userId
        })
      } else {
        // 播放
        pauseSend({
          sceneId: this.sceneId,
          userId: this.userId
        })
      }
    }
  }
}
